from enum import Enum


class State(Enum):
    RUNNING = 1
    STOPED = 2
    WAITING = 3


class Process:
    def __init__(self, arrive_time, burst_time):
        self.arrive_time = arrive_time
        self.burst_time = burst_time
        self._execute_at = None
        self.executed_time = 0
        self.state = State.STOPED

    @property
    def execute_at(self):
        return self._execute_at

    @execute_at.setter
    def execute_at(self, val):
        self._execute_at = val

    @property
    def completed_time(self):
        return self.execute_at + self.burst_time

    def __repr__(self):
        return f'arrive:{self.arrive_time}\nburst:{self.burst_time}\nexecute at:{self.execute_at}\nexcuted:{self.executed_time}\ncompleted at:{self.completed_time}\nstate:{self.state}'


def format(x):
    return round(x, 2)


def fcfs(processes):
    processes.sort(key=lambda x: x)
    if (len(processes) > 1000):
        return None
    processors = [Process(*x) for x in processes]
    queue = []
    exec_proc = None
    time = processes[0][0]
    finished = []
    sum_CT, sum_TAT, sum_WT, sum_Throughput = 0, 0, 0, 0

    while len(finished) < len(processors):
        arrives = [p for p in processors if p.arrive_time == time]
        if arrives:
            queue.extend(arrives)
        #当前没有正在执行的进程且队列里已有等待执行的进程时，弹出并执行第一个等待进程
        if not exec_proc and queue:
            exec_proc = queue.pop(0)
            exec_proc.execute_at = time
            exec_proc.state = State.RUNNING
        if exec_proc:
            exec_proc.executed_time += 1
            if exec_proc.executed_time == exec_proc.burst_time:
                exec_proc.state = State.STOPED

        if exec_proc and exec_proc.state == State.STOPED:
            print(exec_proc)
            print('_______________________________')
            finished.append(exec_proc)
            sum_CT += exec_proc.completed_time
            sum_TAT += exec_proc.completed_time - exec_proc.arrive_time
            sum_WT += exec_proc.completed_time - exec_proc.arrive_time - exec_proc.burst_time
            sum_Throughput += exec_proc.burst_time
            exec_proc = None
        time += 1
    n = len(processes)
    A_CT, A_TAT, A_WT, Throughput = sum_CT / n, sum_TAT / n, sum_WT / n, sum_Throughput / n
    return tuple(map(format, [A_CT, A_TAT, A_WT, Throughput]))


processes = [[32, 15], [48, 36], [35, 10], [27, 46], [39, 37], [38, 35]]
print(fcfs(processes))